//
//  DIYMGJRouter.m
//  SFSC_MGJRouter
//
//  Created by yjs on 2019/11/8.
//  Copyright © 2019 yjs. All rights reserved.
//

#import "DIYMGJRouter.h"
static NSString * const MGJ_ROUTER_WILDCARD_CHARACTER = @"~";

NSString *const MGJRouterParameterURL = @"MGJRouterParameterURL";
NSString *const MGJRouterParameterCompletion = @"MGJRouterParameterCompletion";
NSString *const MGJRouterParameterUserInfo = @"MGJRouterParameterUserInfo";
@implementation DIYMGJRouter

+ (instancetype)sharedInstance{
    static DIYMGJRouter *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //... 不应该是这样写么 DIYMGJRouter alloc.
        instance = [[self alloc] init];
    });
    return instance;
}

+ (void)registerURLPattern:(NSString *)URLPattern toHandler:(MGJRouterHandler)handler{
    [[self sharedInstance] addURLPattern:URLPattern andHandler:handler];
}

- (void)addURLPattern:(NSString *)URLPattern andHandler:(MGJRouterHandler)handler {
    NSLog(@"传入的URLPattern:%@ 刚进来的self.routes：%@",URLPattern,self.routes);
    /*
     刚进来的self.routes：{
     }
     */
    //将传入的url字符串通过一定的格式切割成一个数组
    NSArray *pathComponents = [self pathComponentsFromURL:URLPattern];
    //设置一个索引初始值为 0
    NSInteger index = 0;
    //创建一个临时的字典保存了所有已注册的 URL
    NSMutableDictionary *subRoutes = self.routes;
    //while循环 每循环一次 index + 1 ，直到遍历完 pathComponents 数组的值
    while (index < pathComponents.count) {
        //        NSLog(@"while index:%d",index);
        NSString * pathComponent = pathComponents[index];
        //拿每一个取出的字符串到 已注册的URL字典里获取，如果获取不到 就用当前的字符串做key ， value为一个新的可变空字典
        if (![subRoutes objectForKey:pathComponent]){
            subRoutes[pathComponent] = [[NSMutableDictionary alloc] init];
        }
        //这块作者有点装逼了 一会 objectforkey 一会这样取，也不知道是啥用途,尝试获取刚才设置的空字典？
        subRoutes = subRoutes[pathComponent];
        NSLog(@"subRoutes:%@",subRoutes);
        //while循环需要手动加index的值
        index ++;
    }
    //判断当前传进来的block是否为空
    if (handler){
        //如果不为空的话 设置字典 key 为 下划线_ ，value为传进来的 block
        subRoutes[@"_"] = [handler copy];
        NSLog(@"if (handler):%@",subRoutes);
    }
    NSLog(@"方法执行完毕的self.routes:%@",self.routes);
    /*
      方法执行完毕的self.routes:{
         mgj =     {
             "~" =         {
                 category =             {
                     travel =                 {
                         "_" = "<__NSGlobalBlock__: 0x1003f4158>";
                     };
                 };
             };
         };
     }
     */
}
//来自URL的路径组件
- (NSArray*)pathComponentsFromURL:(NSString*)URL
{
    //1.创建一个路径组件的数组
    NSMutableArray *pathComponents = [NSMutableArray array];
    //2.判断url 是否包含 :// 格式
    if ([URL rangeOfString:@"://"].location != NSNotFound){
        //3.如果不包含 :// (协议格式)
        //4.根据协议格式，将URL字符串里包含协议格式的遇到就分割转换为array数组里的元素
        NSArray *pathSegments = [URL componentsSeparatedByString:@"://"];
        //5.如果 URL 包含协议，那么把协议作为第一个元素放进去
        [pathComponents addObject:pathSegments[0]];
        //6.判断如果只有协议，那么放一个占位符
        if ((pathSegments.count == 2 && ((NSString *)pathSegments[1]).length) || pathSegments.count < 2) {
            [pathComponents addObject:MGJ_ROUTER_WILDCARD_CHARACTER];
        }
        NSLog(@"pathComponents:%@",pathComponents);
        //7.返回一个字符串，这个字符串截取接受对象字符串范围是给定索引index到这个字符串的结尾
        //比如 mgj://foo/bar 这个串， 下面格式location后加4的话 打印出来就剩下：oo/bar
        URL = [URL substringFromIndex:[URL rangeOfString:@"://"].location + 3];
        NSLog(@"URL:%@",URL);
    }
    //遍历 pathComponents 析构路径,获得组成此路径的各个部分
    for (NSString *pathComponent in [[NSURL URLWithString:URL] pathComponents]){
        NSLog(@"pathComponent~:%@",pathComponent);
        //对路径规则的一些处理
        if ([pathComponent isEqualToString:@"/"]) continue;
        if ([[pathComponent substringToIndex:1] isEqualToString:@"1"]) break;
        [pathComponents addObject:pathComponent];
    }
    NSLog(@"最后要返回的pathComponents格式:%@",pathComponents);
    //可变数组这里用copy返回 是害怕后面修改 影响吗？可以测试下
    return [pathComponents copy];
}

- (NSMutableDictionary *)routes
{
    if (!_routes) {
        _routes = [[NSMutableDictionary alloc] init];
    }
    return _routes;
}

+ (void)openURL:(NSString *)URL {
    [self openURL:URL completion:nil];
}

+ (void)openURL:(NSString *)URL completion:(void (^)(void))completion
{
    [self openURL:URL withUserInfo:nil completion:completion];
}

+ (void)openURL:(NSString *)URL withUserInfo:(NSDictionary *)userInfo completion:(void (^)(void))completion
{
    //1.这个方法是用来进行转码的，即将汉字转码.9.0以后换了API
    URL = [URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    //2.返回一个参数字典 key为 url block
    NSMutableDictionary *parameters = [[self sharedInstance] extractParametersFromURL:URL];
    NSLog(@"遍历字典排序前:%@",parameters);
    //3.遍历字典排序
    [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSString class]]){
            parameters[key] = [obj stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        }
    }];
    NSLog(@"排序完:%@",parameters);
    //判断参数字典是否为空
    if (parameters) {
        //获取key为block的 block
        MGJRouterHandler handler = parameters[@"block"];
        //判断参数 如果有的话 设置字典对应key和value值
        if (completion) {
            parameters[MGJRouterParameterCompletion] = completion;
        }
        //把传进来的传参，设置到字典参数里， 判断参数 如果有的话 设置字典对应key和value值
        if (userInfo) {
            parameters[MGJRouterParameterUserInfo] = userInfo;
        }
        //如果block能取到值，就删除key为block的值
        if (handler) {
            [parameters removeObjectForKey:@"block"];
            //通过handler block把参数传出去
            NSLog(@"1+++++++++++++");
            handler(parameters);
            NSLog(@"走了 handler(parameters)");
        }
    }
    NSLog(@"openURl走完 最后的 parameters:%@",parameters);
}

#pragma mark -Utils
- (NSMutableDictionary *)extractParametersFromURL:(NSString *)url {
    //创建一个参数可变字典
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
    //把url赋值给 key 为 MGJRouterParameterURL 的值
    parameters[MGJRouterParameterURL] = url;
    //将已经存在的URL字典赋值给临时字典
    NSMutableDictionary *subRoutes = self.routes;
    //将传入的url字符串通过一定的格式切割成一个数组
    NSArray *pathComponents = [self pathComponentsFromURL:url];
    // borrowed from HHRouter(https://github.com/Huohua/HHRouter)
    //遍历切割后的字符串数组
    for (NSString *pathComponent in pathComponents) {
        //声明一个found默认值为NO
        BOOL found = NO;
        //对 key 进行排序，这样可以把 ~ 放到最后
        NSArray *subRoutesKeys = [subRoutes.allKeys sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
            //
            return [obj1 compare:obj2];
        }];
        //遍历keys
        for (NSString *key in subRoutesKeys) {
            //判断 key 是否和已经分割过数组里的当前遍历字符串相等，或者等于 ~ 号
            if ([key isEqualToString:pathComponent] || [key isEqualToString:MGJ_ROUTER_WILDCARD_CHARACTER]){
                //如果等于的话就是找到了
                found = YES;
                NSLog(@"赋值前:%@",subRoutes);
                subRoutes = subRoutes[key];
                NSLog(@"赋值后:%@",subRoutes);
                /*
                 赋值前:{
                 foo =     {
                 bar =         {
                 "_" = "<__NSGlobalBlock__: 0x10da93138>";
                 };
                 };
                 }
                 赋值后:{
                 bar =     {
                 "_" = "<__NSGlobalBlock__: 0x10da93138>";
                 };
                 }
                 */
                break;
            } else if ([key hasPrefix:@":"]){
                found = YES;
                subRoutes = subRoutes[key];
                parameters[[key substringFromIndex:1]] = pathComponent;
                break;
            }
            
        }
        NSLog(@"extractParametersFromURL里的parameters:%@",parameters);
        //如果最没有找到该 pathComponent 对应的 handler, 则以上一层的 handler 作为 fallback
        if (!found && !subRoutes[@"_"]){
            return nil;
        }
    }
    //Extract ParamsFrom Query.
    NSArray *pathInfo = [url componentsSeparatedByString:@"?"];
    if (pathInfo.count > 1){
        //
        NSString *parametersString = [pathInfo objectAtIndex:1];
        //
        NSArray *paramStringArr = [parametersString componentsSeparatedByString:@"&"];
        //
        for (NSString *paramString in paramStringArr){
            NSArray* paramArr = [paramString componentsSeparatedByString:@"="];
            if (paramArr.count > 1) {
                NSString* key = [paramArr objectAtIndex:0];
                NSString* value = [paramArr objectAtIndex:1];
                parameters[key] = value;
            }
        }
    }
    //
    if (subRoutes[@"_"]) {
        parameters[@"block"] = [subRoutes[@"_"] copy];
    }
    NSLog(@"extractParametersFromURL最终的parameters:%@",parameters);
    /*
     最终的parameters:{
     MGJRouterParameterURL = "mgj://foo/bar";
     block = "<__NSGlobalBlock__: 0x1052b9138>";
     }
     */
    return parameters;
}

@end
